﻿using STHPMS1.BLL.B_Core;
using STHPMS1.ICore.I_BLL.Bus;
using STHPMS1.ICore.I_Entity.Info;
using STHPMS1.ICore.I_Entity.Stmpms1;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using STHPMS1.Common.C_Entity.Stmpms1;
using System.Linq;
using System.Collections;
using STHPMS1.ICore.I_DAL;
using STHPMS1.ICore.I_Serv;
using STHPMS1.ICore;


namespace STHPMS1.BLL.B_Bus
{
    public class Dp_CostbenefitBus : BllBase, IDp_CostbenefitBill
    {
        public void Save<T>(T entity)
            where T : class ,IDp_Costbenefit
        {
            if (this.Scene.Dal.Sthpms1.Update(entity) == 0)
            {
                this.Scene.Dal.Sthpms1.Insert(entity);
            }
        }

        public void Remove(IDp_Costbenefit entity)
        {
            this.Scene.Dal.Sthpms1.Delete(entity);
        }

        public IEnumerable<T> Get<T>(Expression<Func<T, bool>> predicate, IPagingInfo info)
            where T : class, IDp_Costbenefit
        {
            return this.Scene.Dal.Sthpms1.Select<T>(predicate, info,k=>k.Mainsegid,false);
        }

        /// <summary>
        /// 计算效益费用比
        /// </summary>
        /// <param name="rdwayid"></param>
        public void Insert(string anniname, string analy_year)
        {
            IKeyGenrateService serv = MyApp.Locator.GetInstance<IKeyGenrateService>();

            //删除效益分析表中该路段的数据
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            dao.Delete<Dp_Costbenefit>(p => p.Anni_Name == anniname && p.Analy_Year == analy_year);


            Expression<Func<Dp_Preven_Detail, bool>> exp = null;
            if (anniname != null && anniname.ToString().Length > 0 && analy_year != null && analy_year.ToString().Length > 0)
                exp = pre => pre.Anni_Name == anniname.ToString() && pre.Analy_Year == analy_year.ToString() && pre.Secon_Measure == 1 && pre.Preven_Measure == 1;

            List<Dp_Preven_Detail> dp_list = this.Scene.Bll.Dp_Preven_Detail.Get<Dp_Preven_Detail>(exp, null).ToList<Dp_Preven_Detail>();
            foreach (Dp_Preven_Detail info in dp_list)
            {
                Dp_Costbenefit costinfo = new Dp_Costbenefit();
                costinfo.Anni_Name = info.Anni_Name;
                costinfo.Analy_Year = analy_year;
                costinfo.RoadnetId = info.RoadnetId; //路网ID
                costinfo.Rdwayid = info.Rdwayid; //路线编号
                costinfo.Mainsegid = info.Mainsegid; //决策路段
                costinfo.Recomm_Prog = info.Meas_Ini; //推荐方案
                //this.Scene.Bll.Dp_Costbenefit.Save<Dp_Costbenefit>(costinfo);
                //info.Rd_Class//公路等级

                //string StrYear  =dao.Scalar<Dn_Divi_Result, string>(q => q.Rdwayid == info.Rdwayid && q.Mainsegid == info.Mainsegid);

                //通车时间（大修年份）

                //IB_Invntory ib_invntory = dao.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(info.Mainsegid); //基础路段信息

                //int LastYear = dao.Scene.Bll.Dn_Divi_Result.GetLastYear(info.Rdwayid, info.Mainsegid);
                //int LastYear = Convert.ToDateTime(ib_invntory.Begindate).Year ;

                ArrayList arraylist = GetYearArrayList(dao,info.Mainsegid, Convert.ToInt32(info.Rd_Class));  //养护措施年份

                //int maxyear = MaxYear(Convert.ToInt32(info.Rd_Class));  //养护后多少年

                foreach(int year in arraylist)
                {
                    costinfo.Id = serv.NewGuid();
                    costinfo.Pmb = GetPMB(dao,info.Mainsegid,year,info.Meas_Ini, Convert.ToInt32(info.Rd_Class));  //预防性养护效益
                    costinfo.Pbi = GetPBI(dao,info.Mainsegid,year,info.Meas_Ini, Convert.ToInt32(info.Rd_Class)); //预防性养护效益指数
                    double Cost =GetMoney(dao,info, year,info.Meas_Ini);   //
                    costinfo.Present_Cost = Cost/100; //养护费用现值
                    costinfo.Euac = GetMoneyEUAC(dao,info.Mainsegid,Cost, Convert.ToInt32(info.Rd_Class), year,info.Meas_Ini) / 100; //当量平均费用
                    costinfo.Bcr = costinfo.Pbi / costinfo.Euac; //效益费用比
                    costinfo.Main_Year = Convert.ToString(int.Parse(analy_year) + year); //养护年份
                    dao.Insert<Dp_Costbenefit>(costinfo);
                }


            }
        }

        /// <summary>
        /// 获取预防性养护效益
        /// </summary>
        /// <param name="year"></param>
        /// <param name="rd_class"></param>
        /// <returns></returns>
        public double GetPMB(ISthpms1Dao dao,string mainsegid,int year,string meas_ini,int rd_class)
        {
            int minpci = GetMinPCI(rd_class);
            double A1 = GetA1Area(dao,mainsegid,meas_ini, minpci);


            double A2 = GetA2Area(dao,mainsegid,year,minpci);
            double A3 = GetA3Area(A1,A2);
            return A3;
        }

        /// <summary>
        /// 获取预防性养护效益指数
        /// </summary>
        /// <param name="year"></param>
        /// <param name="rd_class"></param>
        /// <returns></returns>
        public double GetPBI(ISthpms1Dao dao, string mainsegid, int year,string meas_ini, int rd_class)
        {
            int minpci = GetMinPCI(rd_class);
            double A3 = GetPMB(dao,mainsegid,year,meas_ini, rd_class);
            double A4 = GetA4Area(dao,mainsegid,minpci);
            return A3 / A4;
        }




        /// <summary>
        /// 原路面的模型
        /// </summary>
        /// <returns></returns>
        public IModelCalculateService RoadModel(string mainsegid)
        {
            ///TODO:模型已经调整
            //IEquation1Service modelServ = this.Scene.Bll.Dm_Modelgroup.GetModelSerivce(mainsegid) as IEquation1Service;
            //return modelServ;
            //IModelCalculateService modelServ=this.Scene.Bll.Dm_Modelgroup.GetModelServ(this.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(mainsegid).Modelgroup_Id);
            //return modelServ;
            return null;
        }

        /// <summary>
        /// 养护后的模型
        /// </summary>
        /// <returns></returns>
        public IEquation2Service MainsegModel()
        {
            ///TODO:模型已经调整
            //IEquation2Service modelServ = this.Scene.Bll.Dm_Modelgroup.Load("养护后预防性养护PCI直线型模型") as IEquation2Service;
            //return modelServ;
            return null;
        }



        /// <summary>
        /// 获取计算效益指数年份
        /// </summary>
        /// <param name="rd_class">技术等级</param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public ArrayList GetYearArrayList(ISthpms1Dao dao, string mainsegid, int rd_class)
        {
            //double a = RoadModel(mainsegid).A;  //原路面模型
            //double b = RoadModel(mainsegid).B;

            string modelGroupID = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == mainsegid).ModelGroup_PCI;
            Dm_Modelgroup model = dao.Single<Dm_Modelgroup>(p => p.Modelgroup_Id == modelGroupID);
            double a = Convert.ToDouble(model.Formulacoeff2);
            double b = Math.Abs(Convert.ToDouble(model.Formulacoeff1));

            //double a = 100;
            //double b = 8.5;

            ArrayList array = new ArrayList();
            if (rd_class == 160 || rd_class == 161)
            {
                //PCI 最大值：90，最小值：80
                int beginYear = Convert.ToInt32((a - 90) / b);
                int endYear = Convert.ToInt32((a - 80) / b);
                for (int i = beginYear; i <= endYear; i++)
                {
                    array.Add(i);
                }
            }
            else
            {
                //PCI 最大值：80 最小值：70
                int beginYear = Convert.ToInt32((a - 80) / b);
                int endYear = Convert.ToInt32((a - 70) / b);
                for (int i = beginYear; i <= endYear; i++)
                {
                    array.Add(i);
                }
            }
            return array;
        }


        /// <summary>
        /// 根据技术等级获取最小值PCI
        /// </summary>
        /// <param name="rd_class"></param>
        /// <returns></returns>
        public int GetMinPCI(int rd_class)
        {
            if (rd_class == 160 || rd_class == 161)
            {
                return 80;
            }
            else
            {
                return 70;
            }
        }

        /// <summary>
        /// 根据技术等级获取最大值PCI
        /// </summary>
        /// <param name="rd_class"></param>
        /// <returns></returns>
        public int GetMaxPCI(int rd_class)
        {
            if (rd_class == 160 || rd_class == 161)
            {
                return 90;
            }
            else
            {
                return 80;
            }
        }


        /// <summary>
        /// 实施后的面积（与年份没有关系，每年都是一样的面积）
        /// </summary>
        /// <param name="a">实施后模型a值</param>
        /// <param name="b">实施后模型b值</param>
        /// <param name="MinPCI"></param>
        /// <returns></returns>
        public double GetA1Area(ISthpms1Dao dao, string mainsegid,string meas_ini, int MinPCI)
        {
            //double a = MainsegModel().A; //实施后模型
            //double b = MainsegModel().B;

            //double a = 100;
            //double b = 6;

            string segid = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == mainsegid).Segid;
            B_Invntory ib_invntory = dao.Single<B_Invntory>(p => p.Segid == segid);
            B_Pmstc b_pmstcinfo = dao.Single<B_Pmstc>(p => p.Rdwayid == ib_invntory.Rdwayid && p.Direction_Dictid == ib_invntory.Direction_Dictid && p.Beginmp <= ib_invntory.Beginmp && p.Endmp >= ib_invntory.Endmp);

            Dm_Modelgroup model = dao.Single<Dm_Modelgroup>(p => p.Pvmttype_Dictid == ib_invntory.Pvmttype_Dictid && p.Basictype_Dictid == ib_invntory.Basictype_Dictid
                && p.Modeltype_Dictid == 12001 && p.Comment == meas_ini && p.Thick_Max >= b_pmstcinfo.Thick_S && p.Thick_Min <= b_pmstcinfo.Thick_S);

            double a = Convert.ToDouble(model.Formulacoeff2);
            double b = Math.Abs(Convert.ToDouble(model.Formulacoeff1));

            double Lenght = (a - MinPCI) / b;
            double Height = a - MinPCI;
            return (Lenght * Height) / 2;
        }

        public int MaxYear(ISthpms1Dao dao, string mainsegid,string meas_ini, int rdclass)
        {
            //double a = MainsegModel().A; //实施后模型
            //double b = MainsegModel().B;
            //double a = 100;
            //double b = 6;

            string segid = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == mainsegid).Segid;
            B_Invntory ib_invntory = dao.Single<B_Invntory>(p => p.Segid == segid);
            B_Pmstc b_pmstcinfo = dao.Single<B_Pmstc>(p => p.Rdwayid == ib_invntory.Rdwayid && p.Direction_Dictid == ib_invntory.Direction_Dictid && p.Beginmp <= ib_invntory.Beginmp && p.Endmp >= ib_invntory.Endmp);

            Dm_Modelgroup model = dao.Single<Dm_Modelgroup>(p => p.Pvmttype_Dictid == ib_invntory.Pvmttype_Dictid && p.Basictype_Dictid == ib_invntory.Basictype_Dictid
                && p.Modeltype_Dictid == 12001 && p.Comment == meas_ini && p.Thick_Max >= b_pmstcinfo.Thick_S && p.Thick_Min <= b_pmstcinfo.Thick_S);

            double a = Convert.ToDouble(model.Formulacoeff2);
            double b = Math.Abs(Convert.ToDouble(model.Formulacoeff1));

            int minpci = GetMinPCI(rdclass);
            return Convert.ToInt32((a - minpci) / b);
        }


        /// <summary>
        /// 第几年原路面的面积
        /// </summary>
        /// <param name="Year">第几年</param>
        /// <param name="a">原路面的a值</param>
        /// <param name="b">原路面的b值</param>
        /// <param name="MinPCI"></param>
        /// <returns></returns>
        public double GetA2Area(ISthpms1Dao dao, string mainsegid, int Year, int MinPCI)
        {
            //double a = RoadModel(mainsegid).A; //原路面模型
            //double b = RoadModel(mainsegid).B;

            string modelGroupID = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == mainsegid).ModelGroup_PCI;
            Dm_Modelgroup model = dao.Single<Dm_Modelgroup>(p => p.Modelgroup_Id == modelGroupID);
            double a = Convert.ToDouble(model.Formulacoeff2);
            double b = Math.Abs(Convert.ToDouble(model.Formulacoeff1));
            //double a = 100;
            //double b = 8.5;

            double Lenght = (a - MinPCI) / b;  //原路面的X值
            double X = Lenght - Year; //长度
            double Y = (a - Year * b)-MinPCI; //高度
            return X*Y/2;
        }

        /// <summary>
        /// 效益
        /// </summary>
        /// <param name="A1">实施后的面积</param>
        /// <param name="A2">第几年原路面的面积</param>
        /// <returns></returns>
        public double GetA3Area(double A1,double A2)
        {
            return A1-A2;
        }


        /// <summary>
        /// 计算A4的面积（原路面的面积）
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="MinPCI"></param>
        /// <returns></returns>
        public double GetA4Area(ISthpms1Dao dao, string mainsegid, int MinPCI)
        {
            //double a = RoadModel(mainsegid).A;//原路面的模型
            //double b = RoadModel(mainsegid).B;

            //STHPMS1.BLL.B_Serv.ModelCalculateService.CreateServiceByModel(model).CalculateY(GetEaslByModel(result, year));

            string modelGroupID = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == mainsegid).ModelGroup_PCI;
            Dm_Modelgroup model = dao.Single<Dm_Modelgroup>(p => p.Modelgroup_Id == modelGroupID);
            double a = Convert.ToDouble(model.Formulacoeff2);
            double b = Math.Abs(Convert.ToDouble(model.Formulacoeff1));
            //double a = 100;
            //double b = 8.5;

            double Lenght = (a - MinPCI) / b;
            double Height = a - MinPCI;
            return (Lenght * Height) / 2;
        }



        /// <summary>
        /// 日常养护费用
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public double RiMoney(Dp_Preven_Detail info)
        {
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;

            Dn_Divi_Result dndrinfo=dao.Single<Dn_Divi_Result>(p => p.Rdwayid == Convert.ToString(info.Rdwayid) && p.Mainsegid == Convert.ToString(info.Mainsegid));
            int pvmttype = 21;

            if (dndrinfo.Pvmttype_Dictid == 165 || dndrinfo.Pvmttype_Dictid == 166 || dndrinfo.Pvmttype_Dictid == 167)
            {
                pvmttype = 21;
            }
            if (dndrinfo.Pvmttype_Dictid == 168 || dndrinfo.Pvmttype_Dictid == 169 || dndrinfo.Pvmttype_Dictid == 170 || dndrinfo.Pvmttype_Dictid == 171)
            {
                pvmttype = 22;
            }
            if (dndrinfo.Pvmttype_Dictid == 172)
            {
                pvmttype = 23;
            }

            //double Daily_Unitcost=this.Scene.Bll.Df_Dailymian_Cost.GetDaily_Unitcost(Convert.ToInt32(dndrinfo.Pvmttype_Dictid), Convert.ToString(dndrinfo.Rdclass_Dictid));

            //通过决策路段获取基础路段信息
            IB_Invntory b_invntoryInfo = this.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(info.Mainsegid);
            int Year = (DateTime.Now - Convert.ToDateTime(b_invntoryInfo.Begindate)).Days/365;

            double Daily_Unitcost = this.Scene.Bll.Df_Dailymian_Cost.GetDaily_Unitcost(pvmttype, Convert.ToString(dndrinfo.Rdclass_Dictid), Year); //通车年限？？？
            double lenght = this.Scene.Bll.Dn_Divi_Result.GetRoadLenght(info.Rdwayid, info.Mainsegid);  //长度
            return Daily_Unitcost * lenght/1000;
        }

        /// <summary>
        /// 预防养护费用
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public double YuMoney(Dp_Preven_Detail info)
        {
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            
            IB_Invntory ib_invntory = this.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(info.Mainsegid); //基础路段信息
            Dn_Divi_Result dndivinfo = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == info.Mainsegid);
            double area = Convert.ToDouble((dndivinfo.Endmp - dndivinfo.Beginmp) * ib_invntory.Surfwidth);  //计算面积
            return area *  Convert.ToDouble(info.Unit_Cost);
        }

        /// <summary>
        /// 折现率
        /// </summary>
        /// <returns></returns>
        public double ZheXian()
        {
            return 0.06;
        }


        /// <summary>
        /// 现值
        /// </summary>
        /// <param name="info"></param>
        /// <param name="year"></param>
        /// <returns></returns>
        public double GetMoney(ISthpms1Dao dao, Dp_Preven_Detail info, int year, string meas_ini)
        {
            double P1 = 0;
            double P2 = 0;
            double P3 = 0;
            double a1 = RiMoney(info);
            double a2 = YuMoney(info)/10000;
            double zhexian = ZheXian();

            for (int i = 1; i < year; i++)
            {
                P1+= a1 / Math.Pow((1 + zhexian), i);
            }

            P2 = a2 / Math.Pow((1 + zhexian), year);



            int maxyear = MaxYear(dao, info.Mainsegid, meas_ini,Convert.ToInt32(info.Rd_Class));
            int begin = year + 1;
            int end = year + maxyear;

            for (int i = begin; i <= end; i++)
            {
                P3 += a1 / Math.Pow((1 + zhexian), i);
            }

            return P1 + P2 + P3;

                
        }

        /// <summary>
        /// 年值
        /// </summary>
        /// <param name="money"></param>
        /// <param name="rdclass"></param>
        /// <param name="year"></param>
        /// <returns></returns>
        public double GetMoneyEUAC(ISthpms1Dao dao, string mainsegid, double money, int rdclass, int year, string meas_ini)
        {
            int maxyear = MaxYear(dao, mainsegid, meas_ini,rdclass);
            int n=year+maxyear;

            double zhexian = ZheXian();
            double EUAC = money * (zhexian * (Math.Pow((1 + zhexian), n)) / (Math.Pow((1 + zhexian), n) - 1));
            return EUAC;
        }

    }
}
